package org.xx.armory.spring5.jpa;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.xx.armory.spring5.data.PageArgs;

import javax.persistence.metamodel.Attribute;

import static org.xx.armory.commons.Validators.rejectIfNull;

public class JpaPageArgs
        extends PageArgs {
    /**
     * 构造分页参数对象。
     *
     * @param startRowIndex
     *         起始记录序号（从0开始）。
     * @param maximumRows
     *         最多记录数。{@code 0} 表示不分页。
     * @param orders
     *         排序规则。
     * @throws IllegalArgumentException
     *         如果参数 {@code startRowIndex} 小于 {@code 0}，或者参数 {@code maximumRows} 小于 {@code 0}。
     */
    private JpaPageArgs(
            int startRowIndex,
            int maximumRows,
            Sort.Order... orders
    ) {
        super(startRowIndex, maximumRows, orders);
    }

    /**
     * 构造一个表示<strong>不分页</strong>的分页参数对象。
     *
     * @return <strong>不分页</strong>的分页参数对象。
     */
    public static JpaPageArgs unpaged() {
        return of(0, 0);
    }

    /**
     * 构造分页参数对象。
     *
     * @param startRowIndex
     *         起始记录序号（从0开始）。
     * @param maximumRows
     *         最多记录数。{@code 0} 表示不分页。
     * @param orders
     *         排序规则。
     * @return 根据分页参数构造的分页参数对象。
     * @throws IllegalArgumentException
     *         如果参数 {@code startRowIndex} 小于 {@code 0}，或者参数 {@code maximumRows} 小于 {@code 0}。
     */
    public static JpaPageArgs of(
            int startRowIndex,
            int maximumRows,
            Sort.Order... orders
    ) {
        return new JpaPageArgs(startRowIndex, maximumRows, orders);
    }

    public static JpaPageArgs of(
            Pageable pageable
    ) {
        return of(pageable.getPageNumber() * pageable.getPageSize(), pageable.getPageSize(), pageable.getSort().stream().toArray(Sort.Order[]::new));
    }

    public final JpaPageArgs asc(
            Attribute<?, ?> attribute
    ) {
        return asc(attribute, Sort.NullHandling.NATIVE);
    }

    public final JpaPageArgs desc(
            Attribute<?, ?> attribute
    ) {
        return desc(attribute, Sort.NullHandling.NATIVE);
    }

    public final JpaPageArgs asc(
            Attribute<?, ?> attribute,
            Sort.NullHandling nullHandling
    ) {
        rejectIfNull(attribute, "attribute");
        rejectIfNull(nullHandling, "nullHandling");

        return (JpaPageArgs) addOrder(Sort.Order.asc(attribute.getName()).with(nullHandling));
    }

    public final JpaPageArgs desc(
            Attribute<?, ?> attribute,
            Sort.NullHandling nullHandling
    ) {
        rejectIfNull(attribute, "attribute");
        rejectIfNull(nullHandling, "nullHandling");

        return (JpaPageArgs) addOrder(Sort.Order.desc(attribute.getName()).with(nullHandling));
    }
}
